﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Unity;
using Silverlight.Weblog.Client.CoreBL.EventAggregator;
using Silverlight.Weblog.Client.CoreBL.Events;
using Silverlight.Weblog.Client.DAL.Events;
using Silverlight.Weblog.Client.DAL.Services;
using Silverlight.Weblog.Client.DAL.ViewModel;
using Silverlight.Weblog.Client.Default.Widgets.BaseUI;
using Silverlight.Weblog.Common.IoC;
using Silverlight.Weblog.Server.DAL;
using System.Linq;
using Silverlight.Weblog.Shared.Common.Web.Helpers;

namespace Silverlight.Weblog.Client.Default.Widgets.ViewModels
{
    public class BlogPostViewModel : ViewModelBase, IBlogPostViewModel, IDisposable
    {
        public BlogPostViewModel()
        {
            IoC.BuildUp(this);

            IoC.Get<IEventAggregator>().GetEvent<LoadBlogPostHTMLEvent>().Subscribe(UpdateViewModel);
            IoC.Get<IEventAggregator>().GetEvent<InitiaPayloadLoadedEvent>().Subscribe(UpdateViewModel_InitiaPayloadLoadedEvent);
            IoC.Get<IEventAggregator>().GetEvent<GoToBlogPostEvent>().Subscribe(UpdateViewModelGoToBlogPostEvent);
            IoC.Get<IEventAggregator>().GetEvent<GoToBlogPostsEvent>().Subscribe(UpdateView_GoToBlogPostsEvent);

            RaiseGoToBlogPostPermlinkEvent = new DelegateCommand<string>(
                (s) => IoC.Get<IEventAggregator>().GetEvent<GoToBlogPostPermlinkEvent>().Publish(s));
        }

        [Dependency]
        public IGoToBlogPostService GoToBlogPostService { get; set; }

        public void UpdateView_GoToBlogPostsEvent(List<BlogPost> obj)
        {
            if (!IsDisplayedInMultiplePanel)
            {
                Model = null;
            }
        }

        public void UpdateViewModelGoToBlogPostEvent(BlogPost obj)
        {
            this.Model = obj;
            this.Html = obj.DisplayHTML;
        }

        public void UpdateViewModel_InitiaPayloadLoadedEvent(User obj)
        {
            if (obj.Posts.Count() == 1)
            {
                var NewModel = obj.Posts.First();

                if (this.Model == null || this.Model.Permlink != NewModel.Permlink)
                    this.Html = NewModel.DisplayHTML;

                this.Model = NewModel;

            }
            else
            {
                if (!IsDisplayedInMultiplePanel)
                {
                    this.Model = null;
                }
            }
        }

        public void UpdateViewModel(BlogPost obj)
        {
            this.Model = obj;
            this.Html = this.Model.DisplayHTML;
        }

        #region Implementation of IDisposable

        public void Dispose()
        {
            IoC.Get<IEventAggregator>().GetEvent<LoadBlogPostHTMLEvent>().Unsubscribe(UpdateViewModel);
            IoC.Get<IEventAggregator>().GetEvent<InitiaPayloadLoadedEvent>().Unsubscribe(UpdateViewModel_InitiaPayloadLoadedEvent);
            IoC.Get<IEventAggregator>().GetEvent<GoToBlogPostEvent>().Unsubscribe(UpdateViewModelGoToBlogPostEvent);
            IoC.Get<IEventAggregator>().GetEvent<GoToBlogPostsEvent>().Unsubscribe(UpdateView_GoToBlogPostsEvent);
        }

        #endregion

        #region FormattedBlogPostCreatedDate
        public string FormattedBlogPostCreatedDate
        {
            get
            {
                if (Model == null || !Model.DateCreated.HasValue)
                    return string.Empty;

                return Model.DateCreated.Value.ToString("dddd, MMMM d, yyyy");
            }
        }

        public string AuthorName
        {
            get
            {
                if (Model == null || Model.User == null)
                    return string.Empty;

                return Model.User.DisplayName;
            }
        }

        public string FiledUnder
        {
            get
            {
                if (Model == null)
                    return string.Empty;

                if (Model.PostCategories.Count == 0)
                    return " | No tags specfied";

                return "| Filed under: ";
            }
        }

        public string CountComments
        {
            get
            {
                if (Model == null)
                    return string.Empty;

                if (Model.Comments.Any() == false)
                    return "No Comments";
                else
                    return Model.Comments.Count() + " Comments";
            }
        }

        public Uri TwitterThisLink
        {
            get
            {
                if (Model == null || Model.User == null)
                    return null;

                if (string.IsNullOrEmpty(Model.User.TwitterUsername))
                    return null;

                return new Uri("http://twitter.com/?status=" +
                                HttpUtility.UrlEncode(string.Format("\"{0}\" by @{1} at {2}",
                                                                     Model.Title,
                                                                     Model.User.TwitterUsername,
                                                                     FullPermlink)));
            }
        }

        public Visibility ShowTwitterLink
        {
            get
            {
                if (Model == null || Model.User == null)
                    return Visibility.Collapsed;

                if (string.IsNullOrEmpty(Model.User.TwitterUsername))
                    return Visibility.Collapsed;
                else
                    return Visibility.Visible;

            }
        }

        #region Html
        private string _html;
        public string Html
        {
            get { return _html; }
            set
            {
                if (_html != value)
                {
                    _html = value;
                    RaisePropertyChanged("Html");
                }

            }
        }
        #endregion Html
        #endregion FormattedBlogPostCreatedDate

        #region Model
        private BlogPost _model;
        public BlogPost Model
        {
            get { return _model; }
            set
            {
                if (_model != value)
                {
                    _model = value;

                    RaisePropertyChanged("Model");
                    RaisePropertyChanged((BlogPostViewModel b) => b.FormattedBlogPostCreatedDate);
                    RaisePropertyChanged((BlogPostViewModel b) => b.AuthorName);
                    RaisePropertyChanged((BlogPostViewModel b) => b.FiledUnder);
                    RaisePropertyChanged((BlogPostViewModel b) => b.CountComments);
                    RaisePropertyChanged((BlogPostViewModel b) => b.TwitterThisLink);
                    RaisePropertyChanged((BlogPostViewModel b) => b.ShowTwitterLink);
                    RaisePropertyChanged((BlogPostViewModel b) => b.BlogPostChildCategoriesViewModels);
                    RaisePropertyChanged((BlogPostViewModel b) => b.FullPermlink);
                    OnModelChanged();
                }

                if (View != null)
                    View.IsActive = (_model != null);
            }
        }

        protected virtual void OnModelChanged()
        {
        }

        #endregion Model

        public override UserControlBase View
        {
            get
            {
                return base.View;
            }
            set
            {
                base.View = value;
                if (Model != null && base.View != null)
                {
                    base.View.IsActive = true;
                }
            }
        }


        public IEnumerable<BlogPostChildCategoriesViewModels> BlogPostChildCategoriesViewModels
        {
            get
            {
                if (Model != null)
                {
                    var postCategories = Model.PostCategories.ToArray();
                    for (int i = 0; i < postCategories.Length; i++)
                    {
                        var postCategory = postCategories[i];
                        yield return new BlogPostChildCategoriesViewModels(postCategory.Category, postCategories.Length == i+1);
                    }
                }

            }
        }

        public string FullPermlink
        {
            get
            {
                if (Model == null || Model.User == null)
                    return null;

                if (Model.User.IsDefaultBlog.HasValue && Model.User.IsDefaultBlog.Value)
                    return Model.User.HomeUrl + "/" + Model.Permlink;
                else
                    return Model.User.HomeUrl + "/" + Model.User.Username + "/" + Model.Permlink; 
            }
        }

        #region RaiseGoToBlogPostPermlinkEvent
        private ICommand _raiseGoToBlogPostPermlinkEvent;
        public ICommand RaiseGoToBlogPostPermlinkEvent
        {
            get { return _raiseGoToBlogPostPermlinkEvent; }
            set
            {
                if (_raiseGoToBlogPostPermlinkEvent != value)
                {
                    _raiseGoToBlogPostPermlinkEvent = value;
                    RaisePropertyChanged("RaiseGoToBlogPostPermlinkEvent");
                }

            }
        }
        #endregion RaiseGoToBlogPostPermlinkEvent

        public bool IsDisplayedInMultiplePanel { get; set; }
    }
}